package org.mobai.flow.strategy;

import org.camunda.bpm.model.bpmn.builder.AbstractFlowNodeBuilder;
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperties;
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperty;
import org.camunda.bpm.model.xml.ModelInstance;
import org.mobai.flow.constant.CamundaConstant;
import org.mobai.flow.enums.ImplementationEnum;
import org.mobai.flow.pojo.bpmn.Listener;
import org.mobai.flow.pojo.bpmn.Node;
import org.mobai.flow.pojo.bpmn.Operations;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * @author hyk
 */
public interface BpmnStrategy<T extends Node> {
    AbstractFlowNodeBuilder build(AbstractFlowNodeBuilder flowNodeBuilder, T node, Map<String, String> nodeMap);


    default void setCamundaExecutionListener(AbstractFlowNodeBuilder flowNodeBuilder, List<Listener> listenerList) {
        Optional.ofNullable(listenerList).ifPresent(listeners -> listeners.forEach(listener -> {
            switch (ImplementationEnum.getByType(listener.getImplementationType())) {
                case CLASS:
                    flowNodeBuilder.camundaExecutionListenerClass(listener.getEvent(), listener.getImplementation());
                    break;

                case DELEGATE_EXPRESSION:
                    flowNodeBuilder.camundaExecutionListenerDelegateExpression(listener.getEvent(), listener.getImplementation());
                    break;
                default:
                    flowNodeBuilder.camundaExecutionListenerExpression(listener.getEvent(), listener.getImplementation());
                    break;
            }
        }));
    }

    /**
     * 设置操作权限
     *
     * @param getOperations
     * @param flowNodeBuilder
     */
    default void setOperations(Operations getOperations, AbstractFlowNodeBuilder flowNodeBuilder, Consumer<CamundaProperties> addOtherPropertiesConsumer) {
        Optional.ofNullable(getOperations).ifPresent(operations -> {
            ModelInstance modelInstance = flowNodeBuilder.getElement().getModelInstance();
            CamundaProperties camundaProperties = modelInstance.newInstance(CamundaProperties.class);

            // 设置驳回
            CamundaProperty back = modelInstance.newInstance(CamundaProperty.class);
            back.setCamundaName(CamundaConstant.OPERATION_BACK);
            back.setCamundaValue(String.valueOf(operations.getBack()));

            // 设置驳回节点
            CamundaProperty backNodeId = modelInstance.newInstance(CamundaProperty.class);
            backNodeId.setCamundaName(CamundaConstant.OPERATION_BACK_NODE);
            backNodeId.setCamundaValue(String.valueOf(operations.getBackNodeId()));

            // 设置完成
            CamundaProperty complete = modelInstance.newInstance(CamundaProperty.class);
            complete.setCamundaName(CamundaConstant.OPERATION_COMPLETE);
            complete.setCamundaValue(String.valueOf(operations.getComplete()));

            // 设置拒绝
            CamundaProperty refuse = modelInstance.newInstance(CamundaProperty.class);
            refuse.setCamundaName(CamundaConstant.OPERATION_REFUSE);
            refuse.setCamundaValue(String.valueOf(operations.getRefuse()));

            // 设置转办
            CamundaProperty transfer = modelInstance.newInstance(CamundaProperty.class);
            transfer.setCamundaName(CamundaConstant.OPERATION_TRANSFER);
            transfer.setCamundaValue(String.valueOf(operations.getTransfer()));

            // 设置委托
            CamundaProperty delegate = modelInstance.newInstance(CamundaProperty.class);
            delegate.setCamundaName(CamundaConstant.OPERATION_DELEGATE);
            delegate.setCamundaValue(String.valueOf(operations.getDelegate()));

            // 设置加签
            CamundaProperty addMulti = modelInstance.newInstance(CamundaProperty.class);
            addMulti.setCamundaName(CamundaConstant.OPERATION_ADD_MULTI);
            addMulti.setCamundaValue(String.valueOf(operations.getAddMulti()));

            // 设置减签
            CamundaProperty minusMulti = modelInstance.newInstance(CamundaProperty.class);
            minusMulti.setCamundaName(CamundaConstant.OPERATION_MINUS_MULTI);
            minusMulti.setCamundaValue(String.valueOf(operations.getMinusMulti()));

            // 将属性添加到元素中
            camundaProperties.addChildElement(back);
            camundaProperties.addChildElement(backNodeId);
            camundaProperties.addChildElement(complete);
            camundaProperties.addChildElement(refuse);
            camundaProperties.addChildElement(transfer);
            camundaProperties.addChildElement(delegate);
            camundaProperties.addChildElement(addMulti);
            camundaProperties.addChildElement(minusMulti);
            addOtherPropertiesConsumer.accept(camundaProperties);
            flowNodeBuilder.addExtensionElement(camundaProperties);

        });
    }
}
